/*
 * usb 最大消息长度是 64 字节.
 * 固定长度 64 + 8 = 72 bytes, 固定数量的内存分配池.
 * 支持 2 个 cpu 同时使用,  使用 spinlock 互斥保护.
 * 单链表保存空闲节点.
 */

#include <stdint.h>
#include <stdlib.h>

#include "hardware/sync.h"
#include "msgpool.h"



#define MSG_SIZE  72

typedef struct _tag_mnode {
	struct _tag_mnode * next;
} mnode_t;


static mnode_t * phead;
static mnode_t * ptail;
static spin_lock_t * plock;

void * msg_alloc( void )
{
	uint32_t saves;
	mnode_t * pnd;

	if ( phead == NULL ) {
		return NULL;
	} 

	saves = spin_lock_blocking( plock );

	/**/
	pnd = phead;

	if ( phead == ptail ) {
		phead = NULL;
		ptail = NULL;
	} else {
		phead = phead->next;
	}

	/**/
	spin_unlock( plock, saves );
	return pnd;
}


void msg_free( void * ptr )
{
	uint32_t saves;
	mnode_t * pnd;

	/**/
	pnd = (mnode_t *)ptr;
	pnd->next = NULL;

	saves = spin_lock_blocking( plock );

	/**/
	if ( ptail != NULL ) {

		ptail->next = pnd;
		ptail = pnd;

	} else {
		phead = pnd;
		ptail = pnd;
	}

	spin_unlock( plock, saves );
	return;
}


int msg_pool_init( int num )
{
	int i;
	uint8_t * ptr;

	phead = NULL;
	ptail = NULL;
	plock = spin_lock_init( PICO_SPINLOCK_ID_OS1 );

	/**/
	ptr = (uint8_t *)malloc( num * MSG_SIZE );
	if ( ptr == NULL ) {
		return 101;
	}

	/**/
	for ( i=0; i<num; i++ ) {
		msg_free( ptr );
		ptr = ptr + MSG_SIZE;
	}

	return 0;
}


